/*
---- 
This file is part of SECONDO.

Copyright (C) 2004, University in Hagen, Department of Computer Science, 
Database Systems for New Applications.

SECONDO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

SECONDO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
----

May, 2007 Leonardo Azevedo, Rafael Brand

*/
#ifndef __RASTER_ALGEBRA_H__
#define __RASTER_ALGEBRA_H__

//#include "Attribute.h"
//#include "../../Tools/Flob/DbArray.h"

#include "Algebra.h"
#include "NestedList.h"
#include "QueryProcessor.h"
#include "StandardTypes.h" //needed because we return a CcBool in an op.
#include <string>
//#include "StandardAttribute.h"
#include "Counter.h"

#include "SpatialAlgebra.h"
#include <fstream>

#include "./Signature/Signature4CRS.h"
#include "Attribute.h"

//#include "DBArray.h"

/*
1.1 Raster4CRS

*/

enum RasterType {RT_REGION, RT_LINE, RT_POINTS};

class Raster4CRS: public Signature4CRS, public Attribute
{
 public:
  //potency dx dy mbr.min.x mbr.min.y mbr.max.x mbr.max.y signature...   
  //DBArray<unsigned long> rasterFLOB;

  int signatureType;
 
  Raster4CRS(){};
  /*
  Do not use this constructor.
  */
  
  Raster4CRS( unsigned long id,  Coordinate min, Coordinate max,
                unsigned long sizeOfBlock, unsigned dx, unsigned dy,
                const Weight weight[], int signature ) : Signature4CRS(id, 
                min, max, sizeOfBlock, dx, dy, weight )//, rasterFLOB(0)
                                              {  
                                                  signatureType = signature;
                                              }
  
  Raster4CRS( const Raster4CRS *raster):Signature4CRS(*(Signature4CRS*)raster)//, rasterFLOB(0)
  {
    this->signatureType = raster->signatureType;
  }
      
  Raster4CRS( const Raster4CRS &raster) : Signature4CRS((Signature4CRS)raster)//, rasterFLOB(0)
  {
    this->signatureType = raster.signatureType;
  }

  Raster4CRS( Signature4CRS::RasterMap4CRS mapaRaster4CRS, 
               int signatureType) : Signature4CRS(mapaRaster4CRS)//, rasterFLOB(0)
  {
    this->signatureType = signatureType;
  }

  //void Raster4CRSToFLOB();
  //void FLOBToRaster4CRS();
  
  ~Raster4CRS();
  Raster4CRS*   Clone() const;

  //int NumOfFLOBs(void) const;
  //FLOB *GetFLOB(const int i);

  Raster4CRS& operator=( Raster4CRS& r );
  
  //functions from StandardAttribute
  //bool IsDefined() const {return true;}
  //void SetDefined( bool Defined ){}
  size_t Sizeof() const { return sizeof(*this); }
  bool Adjacent(const Attribute* arg) const { return false; }
  size_t HashValue() const { return(size_t)(5*map->mbr.min.x + map->mbr.max.y); }
  void CopyFrom( const Attribute* right ) { /*operator=(*((Raster4CRS *)right));*/ }
  int Compare( const Attribute *arg ) const{ return 1;} //still to do

  double checkSimilarity(Raster4CRS* r1, Raster4CRS* r2);
};

void printSignature(const Signature4CRS *raster4CRS);


inline string unsignedLongToBinary( const unsigned long &x ) {
  unsigned long t;
  string ret;
  if( x > 0 ) t = x; else t = -1 * x;
  for( unsigned int i = 0; i < sizeof(unsigned long) * 8; ++i ) 
    if( t & ( 1 << i ) ) ret.push_back( '1' ); else ret.push_back( '0' );
  reverse( ret.begin(), ret.end() );
  if( ret.size() == 0 ) return "0";
  if( x < 0 ) return '-' + ret;
  return ret;
}

class ApproxResult;

class ApproxResult : public Attribute
{
 public:
  inline ApproxResult(){}

  inline ApproxResult( const ApproxResult& other ) 
  {
    result = other.GetResult();
	resultMin = other.GetResultMin();
	resultMax = other.GetResultMax();
  }
  
  inline ApproxResult( double r, double deltaConfidence ) 
  {
    result = r;
	resultMin = r - deltaConfidence;
	resultMax = r + deltaConfidence;

	cout << "result min = " << resultMin << endl;
	cout << "result max = " << resultMax << endl;
  }

  inline ApproxResult( double r, double rmin, double rmax ) 
  {
    result = r;
	resultMin = rmin;
	resultMax = rmax;
  }

  inline ~ApproxResult() 
  { 
  }

  /*inline void Initialize() 
  {}

  inline void Finalize() 
  {}*/

  inline size_t Sizeof() const
  {
    return sizeof( *this );
  }

  inline double GetResult() const
  { 
    return result;
  }

  inline double GetResultMin() const
  { 
    return resultMin;
  }

  inline double GetResultMax() const
  { 
    return resultMax;
  }

  inline ApproxResult* Clone() const
  {
    return (new ApproxResult(this->GetResult(), this->GetResultMin(), this->GetResultMax())); 
  }

  inline size_t HashValue() const
  {
    if(!IsDefined())
      return 0;

    unsigned long h = 0;
    char* s = (char*)&result;
    for(unsigned int i = 1; i <= sizeof(double) / sizeof(char); i++)
    {
      h = 5 * h + *s;
      s++;
    }
    return size_t(h);
  }

  inline void CopyFrom(const Attribute* right)
  {
    const ApproxResult* r = (const ApproxResult*)right;
    SetDefined(r->IsDefined());
	result = r->GetResult();
	resultMin = r->GetResultMin();
	resultMax = r->GetResultMax();
  }

  inline int Compare( const Attribute* arg ) const
  {
	  return 1;
    /*const ApproxResult* rhs = static_cast<const ApproxResult*>( arg );
    static long& ctr = Counter::getRef("ApproxResult::Compare");
    ctr++;
    return Attribute::GenericCompare<ApproxResult>( this, rhs, 
		                              IsDefined(), rhs->IsDefined() );*/
  }

  inline bool Adjacent( const Attribute *arg ) const
  {
    return( CompareAlmost(arg) == 0 );
  }

 private:
  double result;
  double resultMax;
  double resultMin;
};

ostream& operator<<( ostream& o, const ApproxResult& sr );
//ostream& operator<<( ostream& o, const ApproxResult& sr );

#endif
